/*
 * Saphre - Suffix Arrays for Phrase Extraction
 * Copyright (C) 2013 
 * Dale Gerdemann Tübingen, Germany 
 * Niko Schenk Frankfurt am Main, Germany
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */
package collectors.impl;

import collectors.impl.visitors.CollectTraversal;
import collectors.api.Collector1;
import util.Interval;
import saphre.core.Store;
import saphre.core.SuffixArray;
import util.sedgewick.StdOut;
import java.util.ArrayList;
import java.util.List;
import util.sorting.Multiset;
import util.Array;

/**
 * 
 * @author Dale Gerdemann
 */
public class PrintTraversalSL implements Collector1 {

    Store store;
    SuffixArray sa;
    double D;
    Interval top;
    int n = 0;
    Interval[] sufflinks;

    /**
     * 
     * @param store
     * @param sa
     * @param top
     * @param sufflinks 
     */
    public PrintTraversalSL(Store store, SuffixArray sa, Interval top,
                            Interval[] sufflinks) {
        this.store = store;
        this.sa = sa;
        this.top = top;
        this.sufflinks = sufflinks;
        CollectTraversal.pseudoDepth = 0;
    }

    /**
     * 
     * @param pa 
     */
    public void addPrefixArray(SuffixArray pa) {
    }

    /*
     * 
     */
    private String spaces(int n) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 2 * n; i++) {
            sb.append(' ');
        }
        return sb.toString();
    }

    /**
     * 
     * @param inter
     * @param parentLcp
     * @param lcp
     * @param depth 
     */
    @Override
    public void preAdd(Interval inter, int parentLcp, int lcp, int depth) {
    }


    /**
     * 
     * @param inter
     * @param lcp
     * @param depth
     * @param docDist
     * @param leftContext 
     */
    @Override
    public void add(Interval inter, int lcp, int depth, Multiset docDist,
                    Multiset leftContext) {
        if (leftContext.size() != 1 && lcp > 1) {
            boolean exclude = leftContext.size() == 1;
            int loc = sa.getSuftab()[inter.lb()];
            // to print left context: leftContext.toString(store.intToWord, "$")
            // docDist.toString(store.getDocNames(),"?"));

            Multiset dist = inter.following(lcp, sa, store.text);
            StdOut.println(inter.toString(sa, store) + "\n " + inter.tf()
                    + " " + dist.toString(store.intToWord, "$")
                    + "\n");
            if (lcp > 2) {
                int mid = inter.mid(sa.getCldtab());
                Interval sl = sufflinks[mid];


                Multiset slDocDist = sl.docDist(sa, store);
                docDist = sl.docDist(sa, store);
               
                if (sl.tf() > inter.tf()) {
                    int slMid = sl.mid(sa.getCldtab());
                    int slLcp = sl.lcp(slMid, sa.getLcptab());
                    Multiset distLink = sl.following(slLcp, sa, store.text);
                    //System.out.println(distLink.toString(store.intToWord,"$"));
                    double tfRatio = inter.tf() / (double) (sl.tf());

                    List<Integer> winners = new ArrayList<Integer>();
                    double winningNum = -1000000;
                    List<Integer> loosers = new ArrayList<Integer>();
                    double loosingNum = 1000000;

                    for (Multiset.Elem e : distLink.asList()) {
                        int k = e.getKey();
                        double number = dist.cnt(k) - tfRatio * e.getValue();
                        if (number == winningNum) {
                            winners.add(k);
                        }
                        else if (number == loosingNum) {
                            loosers.add(k);
                        }
                        else if (number > winningNum) {

                            winningNum = number;

                            winners = new ArrayList<Integer>();

                            winners.add(k);

                        }
                        else if (number < loosingNum) {
                            loosingNum = number;
                            loosers = new ArrayList<Integer>();
                            loosers.add(k);
                        }
                    }

                    int[] unit = new int[1];
                    int[] interArr = inter.toArray(sa, store);
                    int[] slArr = sl.toArray(sa, store);
                    int[] win;
                    int[] loose;
                    System.out.printf("winners: (%2.1f) \n", winningNum);
                    for (int w : winners) {

                        unit[0] = w;
                        int[] win1 = Array.plus(interArr, unit);
                        win = sa.search(win1).toArray(sa, store);
                        if (win1.length > win.length) {
                            win = win1;
                        }
                        System.out.println(store.toString(win) + " ");
                    }
                    System.out.println();
                    System.out.printf("loosers: (%2.1f) \n", loosingNum);
                    for (int l : loosers) {

                        unit[0] = l;
                        int[] loose1 = Array.plus(slArr, unit);
                        loose = sa.search(loose1).toArray(sa, store);
                        if (loose1.length > loose.length) {
                            loose = loose1;
                        }
                        System.out.println(store.toString(loose));
                    }
                }

            }
            System.out.println("\n\n");

        }
    }

    /**
     * 
     * @param inter
     * @param lcp
     * @param depth
     * @param docDist
     * @param leftContext 
     */
    @Override
    public void addTrivial(Interval inter, int lcp, int depth,
                           Multiset docDist, Multiset leftContext) {
    }
}
